using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using System.Xml;
using System.Text;

namespace WinCommand.SnippetManager
{
	/// <summary>
	/// Main UI for the application. The user interface can either be a fixed
	/// toolwindow or a notification tray icon, depending on a user's preference.
	/// </summary>
	public class SnippetUI : System.Windows.Forms.Form
	{
		#region Declarations, constructors and deconstructors
		internal const string APP_NAME = "Snippet Manager Advanced";
		private const string FILE_FILTER = "Code Snippets (*.snippets)|*.snippets|All files (*.*)|*.*";

		private bool dirtySnippets;				// have snippets changed?
		internal string fileName = "code.snippets";	// default filename
		internal string categoryName = "Common";
		private bool showMiniWindow = true;			// showing mini-window or systray icon

		// Declare the snippets and the UI elements that will display them...
		private ArrayList snippets;
		private CategoryCollection categories;
		private SnippetManagerData data;
		private int tabIndex = 0;

		// All these are created and managed by the WinForms Designer
		private System.Windows.Forms.NotifyIcon notifyIcon;
		private System.Windows.Forms.ContextMenu notifyMenu;
		private System.Windows.Forms.ContextMenu contextMenu;
		private System.Windows.Forms.MenuItem mnuOpenSnippets;
		private System.Windows.Forms.MenuItem mnuSaveSnippets;
		private System.Windows.Forms.MenuItem mnuSeparator1;
		private System.Windows.Forms.MenuItem mnuAddNewSnippet;
		private System.Windows.Forms.MenuItem mnuSeparator2;
		private System.Windows.Forms.MenuItem mnuOrganizeSnippets;
		private System.Windows.Forms.MenuItem mnuOrganizeCategories;
		private System.Windows.Forms.MenuItem mnuMinimizeToSystemTray;
		private System.Windows.Forms.MenuItem mnuRestoreToMiniWindow;
		private System.Windows.Forms.MenuItem mnuExit;
		private System.Windows.Forms.MenuItem mnuSeparator3;
		private System.Windows.Forms.OpenFileDialog openFileDialog;
		private System.Windows.Forms.SaveFileDialog saveFileDialog;
		private System.Windows.Forms.MenuItem mnuSaveSnippetsAs;
		private System.Windows.Forms.ToolTip toolTip1;
		private System.Windows.Forms.MenuItem mnuPasteSnippet;
		private System.Windows.Forms.ComboBox cmbSnippets;
		private System.Windows.Forms.TextBox txtSnippet;
		private System.Windows.Forms.ListBox lstCategories;
		private System.ComponentModel.IContainer components;

		public SnippetUI()
		{
			//
			// Required for Windows Form Designer support
			//
			InitializeComponent();

			// Constructor code specific to SnippetUI
			InitializeSnippetUI();
		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if (components != null) 
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}
		#endregion 

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
            this.components = new System.ComponentModel.Container();
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(SnippetUI));
            this.notifyIcon = new System.Windows.Forms.NotifyIcon(this.components);
            this.notifyMenu = new System.Windows.Forms.ContextMenu();
            this.mnuSeparator3 = new System.Windows.Forms.MenuItem();
            this.mnuRestoreToMiniWindow = new System.Windows.Forms.MenuItem();
            this.mnuExit = new System.Windows.Forms.MenuItem();
            this.contextMenu = new System.Windows.Forms.ContextMenu();
            this.mnuOpenSnippets = new System.Windows.Forms.MenuItem();
            this.mnuSaveSnippets = new System.Windows.Forms.MenuItem();
            this.mnuSaveSnippetsAs = new System.Windows.Forms.MenuItem();
            this.mnuSeparator1 = new System.Windows.Forms.MenuItem();
            this.mnuPasteSnippet = new System.Windows.Forms.MenuItem();
            this.mnuAddNewSnippet = new System.Windows.Forms.MenuItem();
            this.mnuOrganizeSnippets = new System.Windows.Forms.MenuItem();
            this.mnuOrganizeCategories = new System.Windows.Forms.MenuItem();
            this.mnuSeparator2 = new System.Windows.Forms.MenuItem();
            this.mnuMinimizeToSystemTray = new System.Windows.Forms.MenuItem();
            this.openFileDialog = new System.Windows.Forms.OpenFileDialog();
            this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
            this.toolTip1 = new System.Windows.Forms.ToolTip(this.components);
            this.cmbSnippets = new System.Windows.Forms.ComboBox();
            this.txtSnippet = new System.Windows.Forms.TextBox();
            this.lstCategories = new System.Windows.Forms.ListBox();
            this.SuspendLayout();
            // 
            // notifyIcon
            // 
            this.notifyIcon.ContextMenu = this.notifyMenu;
            this.notifyIcon.Icon = ((System.Drawing.Icon)(resources.GetObject("notifyIcon.Icon")));
            this.notifyIcon.DoubleClick += new System.EventHandler(this.mnuRestoreToMiniWindow_Click);
            // 
            // notifyMenu
            // 
            this.notifyMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuSeparator3,
            this.mnuRestoreToMiniWindow,
            this.mnuExit});
            // 
            // mnuSeparator3
            // 
            this.mnuSeparator3.Index = 0;
            this.mnuSeparator3.Text = "-";
            // 
            // mnuRestoreToMiniWindow
            // 
            this.mnuRestoreToMiniWindow.DefaultItem = true;
            this.mnuRestoreToMiniWindow.Index = 1;
            this.mnuRestoreToMiniWindow.RadioCheck = true;
            this.mnuRestoreToMiniWindow.Text = "&Restore To Mini-Window";
            this.mnuRestoreToMiniWindow.Click += new System.EventHandler(this.mnuRestoreToMiniWindow_Click);
            // 
            // mnuExit
            // 
            this.mnuExit.Index = 2;
            this.mnuExit.Text = "E&xit";
            this.mnuExit.Click += new System.EventHandler(this.mnuExit_Click);
            // 
            // contextMenu
            // 
            this.contextMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
            this.mnuOpenSnippets,
            this.mnuSaveSnippets,
            this.mnuSaveSnippetsAs,
            this.mnuSeparator1,
            this.mnuPasteSnippet,
            this.mnuAddNewSnippet,
            this.mnuOrganizeSnippets,
            this.mnuOrganizeCategories,
            this.mnuSeparator2,
            this.mnuMinimizeToSystemTray});
            this.contextMenu.Popup += new System.EventHandler(this.contextMenu_Popup);
            // 
            // mnuOpenSnippets
            // 
            this.mnuOpenSnippets.Index = 0;
            this.mnuOpenSnippets.Text = "Open Snippets...";
            this.mnuOpenSnippets.Click += new System.EventHandler(this.mnuOpenSnippets_Click);
            // 
            // mnuSaveSnippets
            // 
            this.mnuSaveSnippets.Index = 1;
            this.mnuSaveSnippets.Shortcut = System.Windows.Forms.Shortcut.CtrlS;
            this.mnuSaveSnippets.Text = "Save Snippets";
            this.mnuSaveSnippets.Click += new System.EventHandler(this.mnuSaveSnippets_Click);
            // 
            // mnuSaveSnippetsAs
            // 
            this.mnuSaveSnippetsAs.Index = 2;
            this.mnuSaveSnippetsAs.Text = "Save Snippets As...";
            this.mnuSaveSnippetsAs.Click += new System.EventHandler(this.mnuSaveSnippetsAs_Click);
            // 
            // mnuSeparator1
            // 
            this.mnuSeparator1.Index = 3;
            this.mnuSeparator1.Text = "-";
            // 
            // mnuPasteSnippet
            // 
            this.mnuPasteSnippet.Index = 4;
            this.mnuPasteSnippet.Shortcut = System.Windows.Forms.Shortcut.CtrlV;
            this.mnuPasteSnippet.Text = "Paste Snippet";
            this.mnuPasteSnippet.Click += new System.EventHandler(this.mnuPasteSnippet_Click);
            // 
            // mnuAddNewSnippet
            // 
            this.mnuAddNewSnippet.Index = 5;
            this.mnuAddNewSnippet.Shortcut = System.Windows.Forms.Shortcut.CtrlA;
            this.mnuAddNewSnippet.Text = "Add New Snippet...";
            this.mnuAddNewSnippet.Click += new System.EventHandler(this.mnuAddNewSnippet_Click);
            // 
            // mnuOrganizeSnippets
            // 
            this.mnuOrganizeSnippets.Index = 6;
            this.mnuOrganizeSnippets.Text = "Organize Snippets...";
            this.mnuOrganizeSnippets.Click += new System.EventHandler(this.mnuOrganizeSnippets_Click);
            // 
            // mnuOrganizeCategories
            // 
            this.mnuOrganizeCategories.Index = 7;
            this.mnuOrganizeCategories.Text = "Organize Categories...";
            this.mnuOrganizeCategories.Click += new System.EventHandler(this.mnuOrganizeCategories_Click);
            // 
            // mnuSeparator2
            // 
            this.mnuSeparator2.Index = 8;
            this.mnuSeparator2.Text = "-";
            // 
            // mnuMinimizeToSystemTray
            // 
            this.mnuMinimizeToSystemTray.DefaultItem = true;
            this.mnuMinimizeToSystemTray.Index = 9;
            this.mnuMinimizeToSystemTray.RadioCheck = true;
            this.mnuMinimizeToSystemTray.Shortcut = System.Windows.Forms.Shortcut.CtrlShiftM;
            this.mnuMinimizeToSystemTray.Text = "Minimize to System Tray";
            this.mnuMinimizeToSystemTray.Click += new System.EventHandler(this.mnuMinimizeToSystemTray_Click);
            // 
            // toolTip1
            // 
            this.toolTip1.ShowAlways = true;
            // 
            // cmbSnippets
            // 
            this.cmbSnippets.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.cmbSnippets.ContextMenu = this.contextMenu;
            this.cmbSnippets.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
            this.cmbSnippets.Font = new System.Drawing.Font("Lucida Console", 8.25F);
            this.cmbSnippets.Location = new System.Drawing.Point(0, 50);
            this.cmbSnippets.Name = "cmbSnippets";
            this.cmbSnippets.Size = new System.Drawing.Size(368, 19);
            this.cmbSnippets.TabIndex = 2;
            this.cmbSnippets.SelectedIndexChanged += new System.EventHandler(this.cmbSnippets_SelectedIndexChanged);
            // 
            // txtSnippet
            // 
            this.txtSnippet.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.txtSnippet.ContextMenu = this.contextMenu;
            this.txtSnippet.Font = new System.Drawing.Font("Lucida Console", 8.25F);
            this.txtSnippet.Location = new System.Drawing.Point(0, 71);
            this.txtSnippet.Multiline = true;
            this.txtSnippet.Name = "txtSnippet";
            this.txtSnippet.ReadOnly = true;
            this.txtSnippet.ScrollBars = System.Windows.Forms.ScrollBars.Vertical;
            this.txtSnippet.Size = new System.Drawing.Size(368, 105);
            this.txtSnippet.TabIndex = 3;
            // 
            // lstCategories
            // 
            this.lstCategories.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.lstCategories.ContextMenu = this.contextMenu;
            this.lstCategories.Font = new System.Drawing.Font("Lucida Console", 8.25F);
            this.lstCategories.ItemHeight = 11;
            this.lstCategories.Location = new System.Drawing.Point(0, 0);
            this.lstCategories.Name = "lstCategories";
            this.lstCategories.Size = new System.Drawing.Size(368, 48);
            this.lstCategories.TabIndex = 4;
            this.lstCategories.SelectedIndexChanged += new System.EventHandler(this.lstCategories_SelectedIndexChanged);
            // 
            // SnippetUI
            // 
            this.AllowDrop = true;
            this.AutoScaleBaseSize = new System.Drawing.Size(5, 14);
            this.BackColor = System.Drawing.SystemColors.Control;
            this.ClientSize = new System.Drawing.Size(368, 176);
            this.ContextMenu = this.contextMenu;
            this.Controls.Add(this.lstCategories);
            this.Controls.Add(this.txtSnippet);
            this.Controls.Add(this.cmbSnippets);
            this.DoubleBuffered = true;
            this.Font = new System.Drawing.Font("Tahoma", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
            this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
            this.Name = "SnippetUI";
            this.Opacity = 0.4;
            this.ShowInTaskbar = false;
            this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
            this.TopMost = true;
            this.Deactivate += new System.EventHandler(this.SnippetUI_Deactivate);
            this.DragDrop += new System.Windows.Forms.DragEventHandler(this.SnippetUI_DragDrop);
            this.Closed += new System.EventHandler(this.SnippetUI_Closed);
            this.DoubleClick += new System.EventHandler(this.mnuMinimizeToSystemTray_Click);
            this.Activated += new System.EventHandler(this.SnippetUI_Activated);
            this.Closing += new System.ComponentModel.CancelEventHandler(this.SnippetUI_Closing);
            this.DragEnter += new System.Windows.Forms.DragEventHandler(this.SnippetUI_DragEnter);
            this.ResumeLayout(false);
            this.PerformLayout();

		}
		#endregion
        
		/////////////////////////////////////////////////////////////////////////////////////////////
		// EVENT HANDLERS
		/////////////////////////////////////////////////////////////////////////////////////////////

		private void OnLinkClick(object sender, System.Windows.Forms.LinkLabelLinkClickedEventArgs e)
		{			
			
			CopySnippetToClipboard((int)((LinkLabel)sender).Tag);
			//MessageBox.Show(this, "Copied to Clipboard", SnippetUI.APP_NAME, MessageBoxButtons.OK, MessageBoxIcon.Information);
		}
		private void OnLinkMouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
		{
			
			MessageBox.Show("Click");
			//CopySnippetToClipboard((int)((LinkLabel)sender).Tag);
		}
		
		// Code to support dragging doesn't work yet...
		private void OnLinkMouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
		{
//             Tells Windows that this object can be dragged and dropped
//			 The casting is tortuous, unfortunately:
//			     a. (LinkLabel)sender           = LinkLabel that generated this event
//			     b. (int)a.Tag                  = index of that snippet within the collection
//			     c. ((Snippet)snippets[b]).Code = the code snippet itself
//
			if (e.Button == MouseButtons.Right)
			{
				((LinkLabel)sender).DoDragDrop(
					((Snippet)snippets[((int)((LinkLabel)sender).Tag)]).Code,
					DragDropEffects.Copy);	// only copy, not move
			}
		}
		
		private void OnMenuItemClick(object sender, EventArgs e)
		{
			if (typeof(SnippetMenuItem).IsInstanceOfType(sender))
			{
				CopySnippetToClipboard(((SnippetMenuItem)sender).SnippetIndex);
			}
		}


		private void mnuOpenSnippets_Click(object sender, System.EventArgs e)
		{
			openFileDialog.Filter = FILE_FILTER;
			DialogResult dlg = openFileDialog.ShowDialog();
			if (dlg == DialogResult.OK)
			{
				// set new default filename
				fileName = openFileDialog.FileName;
				data = SnippetData.DeserializeSnippets(fileName);
				categories = data.Categories;
				snippets = data.Snippets;				
				if (snippets.Count == 0)
				{
					if (categories.Count == 0)
					{
						// add a default category otherwise it's not
						// possible to add snippets
						categories.Add(categoryName);
					}
				}
				SynchronizeView();
			}
		}


		private void mnuSaveSnippets_Click(object sender, System.EventArgs e)
		{
			SnippetData.SerializeSnippets(fileName, data);
			dirtySnippets = false;
		}


		private void mnuSaveSnippetsAs_Click(object sender, System.EventArgs e)
		{
			saveFileDialog.Filter = FILE_FILTER;
			DialogResult dlg = saveFileDialog.ShowDialog();
			if (dlg == DialogResult.OK)
			{
				SnippetData.SerializeSnippets(saveFileDialog.FileName, data);
				dirtySnippets = false;
			}
		}

		private void mnuPasteSnippet_Click(object sender, System.EventArgs e)
		{
			IDataObject data = Clipboard.GetDataObject();
			if (data.GetDataPresent(DataFormats.Text))
			{
				Snippet s = new Snippet();
				s.Name = SnippetData.GetUniqueName(snippets);
				s.Code = (string)data.GetData(DataFormats.Text);
				s.Category = lstCategories.Text;
				snippets.Add(s);
				dirtySnippets = true;	

				SynchronizeView(false);
			}
		
		}

		private void mnuAddNewSnippet_Click(object sender, System.EventArgs e)
		{
			AddNewSnippet addSnippet = new AddNewSnippet();
			addSnippet.Width = Width;
			addSnippet.Height = Height;
			addSnippet.Location = Location;

			addSnippet.Categories = categories;
			addSnippet.Snippets = snippets;
			addSnippet.ShowDialog(this);
			if (addSnippet.DialogResult == DialogResult.OK)
			{
				if (addSnippet.SnippetCategory == String.Empty)
				{
					snippets.Add(new Snippet(addSnippet.SnippetName, addSnippet.SnippetCode));
				}
				else
				{
					snippets.Add(new Snippet(addSnippet.SnippetName, addSnippet.SnippetCode, addSnippet.SnippetCategory));
				}
				dirtySnippets = true;

				SynchronizeView(false);

				SnippetData.SerializeSnippets(fileName, data);
				dirtySnippets = false;
			}
			addSnippet.Dispose();
		}


		private void mnuOrganizeSnippets_Click(object sender, System.EventArgs e)
		{
			OrganizeSnippets orgSnippets = new OrganizeSnippets();
			orgSnippets.Snippets = snippets;
			orgSnippets.Categories = categories;
			orgSnippets.SelectedCategory = cmbSnippets.SelectedIndex;
			orgSnippets.ShowDialog(this);

			// If the user clicked OK, then we replace the current copy of the 
			// snippets with the new one, and update the view. If the user 
			// clicked Cancel, we simply discard all changes.
			if (orgSnippets.DialogResult == DialogResult.OK)
			{

				snippets = orgSnippets.Snippets;
				categories = orgSnippets.Categories;
				dirtySnippets = true;

				SynchronizeView(false);
			}
			orgSnippets.Dispose();

		}

		private void mnuOrganizeCategories_Click(object sender, System.EventArgs e)
		{
			

			OrganizeCategories orgCategories = new OrganizeCategories();
			orgCategories.Categories = categories;
			orgCategories.Snippets = snippets;
			orgCategories.ShowDialog(this);

			// If the user clicked OK, then we replace the current copy of the 
			// snippets with the new one, and update the view. If the user 
			// clicked Cancel, we simply discard all changes.
			if (orgCategories.DialogResult == DialogResult.OK)
			{

				snippets = orgCategories.Snippets;
				categories = orgCategories.Categories;
				dirtySnippets = true;
				
				SynchronizeView(false);

			}
			orgCategories.Dispose();
		}

		private void mnuMinimizeToSystemTray_Click(object sender, System.EventArgs e)
		{
			tabIndex = lstCategories.SelectedIndex;

			this.Visible = false;
			notifyIcon.Visible = true;
			showMiniWindow = false;
			SynchronizeView();
		}


		private void mnuRestoreToMiniWindow_Click(object sender, System.EventArgs e)
		{
			this.Visible = true;
			notifyIcon.Visible = false;
			showMiniWindow = true;

			lstCategories.SuspendLayout();
			this.SuspendLayout();

			SynchronizeView(false);

			lstCategories.SelectedIndex = tabIndex;

			lstCategories.ResumeLayout();

			this.ResumeLayout();
		}


		private void mnuExit_Click(object sender, System.EventArgs e)
		{
			if (WeCanExit())
			{
				this.notifyIcon.Visible = false;
				Application.Exit();
			}
		}


		private void SnippetUI_Closing(object sender, System.ComponentModel.CancelEventArgs e)
		{
			//e.Cancel = !WeCanExit();
			SnippetData.SerializeSnippets(fileName, data);
			dirtySnippets = false;
		}

		private void SnippetUI_Closed(object sender, System.EventArgs e)
		{
			this.notifyIcon.Visible = false;
		}


		private void SnippetUI_DragEnter(object sender, System.Windows.Forms.DragEventArgs e)
		{			
			if (e.Data.GetDataPresent(DataFormats.Text))
			{
				e.Effect = DragDropEffects.Copy;
			}
			else
			{
				e.Effect = DragDropEffects.None;
			}
		}

		
		private void SnippetUI_DragDrop(object sender, System.Windows.Forms.DragEventArgs e)
		{
			string code = (string)e.Data.GetData(DataFormats.Text);

			
//			TabPage tab = tabControl1.SelectedTab;
//			System.Drawing.Point p = tab.PointToClient(new System.Drawing.Point(e.X, e.Y));
//			Control ctl = tab.GetChildAtPoint(p);
//
//			if (ctl != null)
//			{
//				System.Diagnostics.Debug.Write(ctl.Text);
//				if (typeof(LinkLabel).IsInstanceOfType(ctl))
//				{
//					LinkLabel link = (LinkLabel)ctl;
//					string oldLinkCode = ((Snippet)snippets[(int)link.Tag]).Code;
//					if (code == oldLinkCode)
//					{
//						return;
//					}
//
//				}
//			}
			
			// save selected tabindex for restore

			Snippet draggedItem = new Snippet();
			draggedItem.Name = SnippetData.GetUniqueName(snippets);
			draggedItem.Code = code;
			draggedItem.Category = lstCategories.Text;

			snippets.Add(draggedItem);
			dirtySnippets = true;

			SynchronizeView(false);
		}



		/////////////////////////////////////////////////////////////////////////////////////////////
		// PRIVATE METHODS
		/////////////////////////////////////////////////////////////////////////////////////////////

		/// <summary>
		/// Initialize the application
		/// </summary>
		private void InitializeSnippetUI()
		{
			// SnippetManager constructor code
			this.Text = APP_NAME;
			this.notifyIcon.Text = APP_NAME;
			showMiniWindow = true;

			data = SnippetData.DeserializeSnippets(fileName);
			categories = data.Categories;
			snippets = data.Snippets;

			if (snippets.Count == 0)
			{
				if (categories.Count == 0)
				{
					// Add a default category, otherwise it's
					// not possible to add snippets
					categories.Add(categoryName);
				}
			}
			
			SynchronizeView();
		}


		/// <summary>
		/// Keeping the internal data collection (snippets) synchronized with the 
		/// presentation of that object is not simple, as can be seen by the quantity
		/// of code below. Rather than trying to keep the two in sync throughout the
		/// code base, we simply call this function whenever anything changes to the
		/// underlying data. The disadvantage is that we spend more time repopulating
		/// the UI than is absolutely necessary (we delete and recreate everything even
		/// if only one thing has changed); the advantage is that the code is neat and
		/// simple, with only one place to update any display logic. Given the small
		/// number of snippets to be displayed, it's worth the perf hit.
		/// </summary>
		private void SynchronizeView(bool suspend)
		{	
			int elem = 0;

			if (suspend) { this.SuspendLayout(); }

			// Save some resources. We show either the mini-window or the system tray
			// icon (never both at once) - therefore we only populate one or the other at
			// any given time. We call this method when switching views too, to ensure
			// that the appropriate one is populated.
			
			// Populate the mini-window
			if (showMiniWindow) // showing mini-window
			{
				int lstCategoriesIndex = lstCategories.SelectedIndex;
				int cmbSnippetsIndex = cmbSnippets.SelectedIndex;

				this.lstCategories.Items.Clear();
				this.cmbSnippets.Items.Clear();
				this.txtSnippet.Text = string.Empty;

				foreach(Category category in categories)
				{
					lstCategories.Items.Add(category.Name);
				}

				lstCategories.SelectedIndex = lstCategoriesIndex;
				if(lstCategoriesIndex != -1) cmbSnippets.SelectedIndex = cmbSnippetsIndex;
			}
			// Populate the notification icon context menu
			else // showing notification icon
			{
				// The last three entries are always present (separator, restore and exit 
				// commands). We clear everything else...
				for(int i = 0, menuItemsToDelete = notifyMenu.MenuItems.Count - 3; i < menuItemsToDelete; i++)
				{
					notifyMenu.MenuItems.RemoveAt(0);
				}


				int categoryIndex = 0;
				foreach(Snippet s in snippets)
				{
					// Find or create TabPages					
					MenuItem cMenu = FindCategoryMenuItem(s.Category);
					if (cMenu == null) 
					{ 
						cMenu = CreateCategoryMenuItem(s.Category); 
						cMenu.Index = categoryIndex++;
						if (!CategoryExist(s.Category)) { categories.Add(s.Category); }
					}
										
					SnippetMenuItem sMenu = new SnippetMenuItem(s.Name);
					sMenu.Click += new EventHandler(OnMenuItemClick);
					cMenu.MenuItems.Add(sMenu);					
					sMenu.SnippetIndex = elem++;		
				}
			}
			if (suspend) { this.ResumeLayout(); }
		}

		private void SynchronizeView()
		{
			SynchronizeView(true);
		}

		private MenuItem FindCategoryMenuItem(string categoryName)
		{
			MenuItem foundItem = null;
			foreach (MenuItem item in notifyMenu.MenuItems)
			{
				if (item.Text == categoryName)
				{
					foundItem = item;
					break;
				}
			}
			return foundItem;
		}

		private MenuItem CreateCategoryMenuItem(string categoryName)
		{
			MenuItem item = new MenuItem(categoryName);
			notifyMenu.MenuItems.Add(item);
			return item;
		}

		/// <summary>
		/// Checks if a category allready exists
		/// </summary>
		/// <param name="name">name of the category</param>
		/// <returns>true if category exists, otherwise false</returns>
		private bool CategoryExist(string name)
		{
			bool result = false;
			foreach(Category category in categories)
			{
				if (category.Name == name)
				{
					result = true;
					break;
				}
			}
			return result;
		}

		/// <summary>
		/// Copies the code for a given snippet to the Windows Clipboard.
		/// </summary>
		private void CopySnippetToClipboard(int snippetIndex)
		{
			// Leave the snippet on the clipboard even if the application is closed
			Clipboard.SetDataObject(((Snippet)snippets[snippetIndex]).Code, true);
		}


		/// <summary>
		/// Determines whether it is safe to exit (are there any unsaved
		/// changes to be persisted to disk?)
		/// </summary>
		private bool WeCanExit()
		{	bool result = true;
			if (dirtySnippets)
			{
				DialogResult dlg = MessageBox.Show("Do you want to save the changes you made to the snippets?", APP_NAME, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Exclamation);
				switch (dlg)
				{
					case DialogResult.Yes:
						SnippetData.SerializeSnippets(fileName, data);
						break;
					case DialogResult.No:
						break;
					default:
						result = false;
						break;
				}
			}
			return result;
		}

		/// <summary>
		/// Attaches a tooltip to a control
		/// </summary>
		/// <param name="ctl">the control</param>
		/// <param name="msg">tooltip text</param>
		private void CreateToolTipForControl(Control ctl, String msg)
		{
			// split by carridge return
			String[] lines = msg.Split(new char[] {'\u000D'});
			// StringBuilder is faster
			StringBuilder sb = new StringBuilder();
			// maximum lines
			int lineCount = lines.Length;			
			if (lineCount > 24)
			{
				// only show 24 lines
				lineCount = 24;
			}

			for (int i = 0; i < lineCount; i++)
			{
				// tab-character
				char tab = '\u0009';
				// line-feed-character
				char lf = '\u000A';
				// must replace tabs with whitespace to show properly
				String line = lines[i].Replace(tab.ToString(), "    ");
				// must replace line-feeds to show properly
				line = line.Replace(lf.ToString(), "");
				// append String
				sb.Append(line + "\n");
			}

			// append 3 dots if text exceeds more than 24 lines
			if (lines.Length > lineCount)
			{
				sb.Append("...");
			}

			// attache tooltip to control
			toolTip1.SetToolTip(ctl, sb.ToString());
		}

		private void contextMenu_Popup(object sender, System.EventArgs e)
		{
			IDataObject data = Clipboard.GetDataObject();
			this.mnuPasteSnippet.Enabled = data.GetDataPresent(DataFormats.Text);	
			
		}

		private void lstCategories_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			cmbSnippets.Items.Clear();
			txtSnippet.Text = string.Empty;
			foreach (Snippet s in snippets){
				if(s.Category.Equals(lstCategories.Text))
					cmbSnippets.Items.Add(s);
			}
		}

		private void cmbSnippets_SelectedIndexChanged(object sender, System.EventArgs e)
		{
			txtSnippet.Text = ((Snippet)cmbSnippets .SelectedItem).Code;
		}

		private void SnippetUI_Deactivate(object sender, System.EventArgs e) {
			Opacity = 0.4;
		}

		private void SnippetUI_Activated(object sender, System.EventArgs e) {
			Opacity = 1.0;
		}
	}

	public class SnippetMenuItem : MenuItem
	{
		private int snippetIndex = -1;

		public SnippetMenuItem() : base()
		{
		}
		public SnippetMenuItem(string text) : base(text)
		{
		}
		public int SnippetIndex
		{
			get
			{
				return snippetIndex;
			}
			set
			{
				snippetIndex = value;
			}
		}

	}

}
